//
// Created by work on 24-8-30.
//

#include "iot_model_device/device_model_mgr/CModelMgr.h"

[[maybe_unused]] bool CModelMgr::addModel(const CModelInfo &model) {
    return (CSsqlMgr::addModel(model) && (CRedisDbMgr::loadModel(model.user, model.name)));
}

[[maybe_unused]] bool iotplat::CModelMgr::getRtModel(std::string &userid, std::string &modelName, iotplat::CModelInfo &model) {
    return CRedisDbMgr::getRtModel(userid, modelName, model);
}

[[maybe_unused]] bool iotplat::CModelMgr::getRtModels(std::string &userid, std::vector<CModelInfo> &models) {
    std::unordered_set<std::string> idxs;
    if(!CRedisDbMgr::getModelIndexs(userid, idxs)) {
        return false;
    }

    for(std::string index : idxs) {
        CModelInfo model;
        if(!CRedisDbMgr::getRtModel(userid, index, model)) {
            return false;
        }
        models.push_back(model);
    }
    return true;
}

[[maybe_unused]] bool iotplat::CModelMgr::getDataBaseModel(std::string &userid, std::string &modelName, iotplat::CModelInfo &model) {
    return CSsqlMgr::getModel(userid, modelName, model);
}

[[maybe_unused]] bool iotplat::CModelMgr::getDataBaseModels(std::string &userid, std::vector<CModelInfo> &models) {
    return CSsqlMgr::getModels(userid, models);
}

[[maybe_unused]] bool iotplat::CModelMgr::delModel(std::string &userid, std::string &modelName) {
    return (CRedisDbMgr::unLoadModel(userid, modelName) && (CSsqlMgr::delModel(userid, modelName)));
}

[[maybe_unused]] bool iotplat::CModelMgr::changeModel(const iotplat::CModelInfo &model) {
    return (CSsqlMgr::changeModel(model) && CRedisDbMgr::loadModel(model.user, model.name));
}

bool CModelMgr::addDevice(CRtDeviceInfo &device) {
    return (CSsqlMgr::addDevice(device) && CRedisDbMgr::loadModel(device.user, device.name));
}

bool CModelMgr::delDevice(std::string &userid, std::string &modelName, std::string &deviceName) {
    return true;
}

bool CModelMgr::changeDevice(CRtDeviceInfo &device) {
    return (CSsqlMgr::changeDevice(device) && CRedisDbMgr::loadModel(device.user, device.name));
}

bool CModelMgr::getDbDevice(std::string &userid, std::string &modelName, std::string &deviceName, CRtDeviceInfo& device) {
    return CSsqlMgr::getDevice(userid, modelName, deviceName, device);
}

bool CModelMgr::getRtDevice(std::string &userid, std::string &modelName, std::string &deviceName, CRtDeviceInfo& device) {
    return CRedisDbMgr::getRtDevice(userid, modelName, deviceName, device);
}

bool CModelMgr::getDevicesByModel(std::string &userid, std::string &modelName, std::vector<CRtDeviceInfo> &devices) {
    return CSsqlMgr::getDevices(userid, modelName, devices);
}

bool CModelMgr::getRtDevicesByModel(std::string &userid, std::string &modelName, std::vector<CRtDeviceInfo> &devices) {
    return CRedisDbMgr::getRtDevices(userid, modelName, devices);
}

/********************************************************yx相关***************************************************************/
bool CModelMgr::addModelYx(CRtModelYxInfo &yx) {
    return (CSsqlMgr::addyx(yx) && CRedisDbMgr::loadModelYx(yx.user, yx.model_name, yx.name));
}

[[maybe_unused]] bool iotplat::CModelMgr::getRtModelYx(std::string &userid, std::string &modelName, std::string &yxName, iotplat::CRtModelYxInfo &yx) {
    return CRedisDbMgr::getRtModelYx(userid, modelName, yxName, yx);
}

[[maybe_unused]] bool iotplat::CModelMgr::getRtModelYxs(std::string &userid, std::string &modelName, std::vector<CRtModelYxInfo> &yxs) {
    std::unordered_set<std::string> names;
    if(!CRedisDbMgr::getModelYxIndexs(userid, modelName, names))
        return false;

    for(std::string name : names) {
        CRtModelYxInfo yx;
        if(!CRedisDbMgr::getRtModelYx(userid, modelName, name, yx)) {
            return false;
        }
        yxs.push_back(yx);
    }
    return true;
}

[[maybe_unused]] bool iotplat::CModelMgr::getDataBaseModelYx(std::string &userid, std::string &modelName, std::string &yxName,iotplat::CRtModelYxInfo &yx) {
    return CSsqlMgr::getYx(userid, modelName, yxName, yx);
}

[[maybe_unused]] bool iotplat::CModelMgr::getDataBaseModelYxs(std::string &userid, std::string &modelName, std::vector<CRtModelYxInfo> &yxs) {
    return CSsqlMgr::getYxs(userid, modelName, yxs);
}

[[maybe_unused]] bool iotplat::CModelMgr::delModelYx(std::string &userid, std::string &modelName, std::string &yxName) {
    return (CRedisDbMgr::unLoadModelYx(userid, modelName, yxName) && CSsqlMgr::delYx(userid, modelName, yxName));
}

[[maybe_unused]] bool iotplat::CModelMgr::changeModelYx(iotplat::CRtModelYxInfo &yx) {
    return (CSsqlMgr::changeYx(yx) && !CRedisDbMgr::loadModelYx(yx.user, yx.model_name, yx.name));
}

/********************************************************yc相关***************************************************************/
bool CModelMgr::addModelYc(CRtModelYcInfo &yc) {
    return (CSsqlMgr::addyc(yc) && CRedisDbMgr::loadModelYc(yc.user, yc.model_name, yc.name));
}

[[maybe_unused]] bool iotplat::CModelMgr::getRtModelYc(std::string &userid, std::string &modelName, std::string &ycName, iotplat::CRtModelYcInfo &yc) {
    return CRedisDbMgr::getRtModelYc(userid, modelName, ycName, yc);
}

[[maybe_unused]] bool iotplat::CModelMgr::getRtModelYcs(std::string &userid, std::string &modelName, std::vector<CRtModelYcInfo> &ycs) {
    std::unordered_set<std::string> names;
    if(!CRedisDbMgr::getModelYcIndexs(userid, modelName, names))
        return false;

    for(std::string name : names) {
        CRtModelYcInfo yc;
        if(!CRedisDbMgr::getRtModelYc(userid, modelName, name, yc)) {
            return false;
        }
        ycs.push_back(yc);
    }
    return true;
}

[[maybe_unused]] bool iotplat::CModelMgr::getDataBaseModelYc(std::string &userid, std::string &modelName, std::string &ycName,iotplat::CRtModelYcInfo &yc) {
    return CSsqlMgr::getYc(userid, modelName, ycName, yc);
}

[[maybe_unused]] bool iotplat::CModelMgr::getDataBaseModelYcs(std::string &userid, std::string &modelName, std::vector<CRtModelYcInfo> &ycs) {
    return CSsqlMgr::getYcs(userid, modelName, ycs);
}

[[maybe_unused]] bool iotplat::CModelMgr::delModelYc(std::string &userid, std::string &modelName, std::string &ycName) {
    return (CRedisDbMgr::unLoadModelYc(userid, modelName, ycName) && CSsqlMgr::delYc(userid, modelName, ycName));
}

[[maybe_unused]] bool iotplat::CModelMgr::changeModelYc(const iotplat::CRtModelYcInfo &yc) {
    return (CSsqlMgr::changeYc(yc) && CRedisDbMgr::loadModelYc(yc.user, yc.model_name, yc.name));
}

/********************************************************yk相关***************************************************************/
bool CModelMgr::addModelYk(CRtModelYkInfo &yk) {
    return (CSsqlMgr::addyk(yk) && CRedisDbMgr::loadModelYk(yk.user, yk.model_name, yk.name));
}

[[maybe_unused]] bool iotplat::CModelMgr::getRtModelYk(std::string &userid, std::string &modelName, std::string &ykName, iotplat::CRtModelYkInfo &yk) {
    return CRedisDbMgr::getRtModelYk(userid, modelName, ykName, yk);
}

[[maybe_unused]] bool iotplat::CModelMgr::getRtModelYks(std::string &userid, std::string &modelName, std::vector<CRtModelYkInfo> &yks) {
    std::unordered_set<std::string> names;
    if(!CRedisDbMgr::getModelYkIndexs(userid, modelName, names))
        return false;

    for(std::string name : names) {
        CRtModelYkInfo yk;
        if(!CRedisDbMgr::getRtModelYk(userid, modelName, name, yk)) {
            return false;
        }
        yks.push_back(yk);
    }
    return true;
}

[[maybe_unused]] bool iotplat::CModelMgr::getDataBaseModelYk(std::string &userid, std::string &modelName, std::string &ykName, iotplat::CRtModelYkInfo &yk) {
    return CSsqlMgr::getYk(userid, modelName, ykName, yk);
}

[[maybe_unused]] bool iotplat::CModelMgr::getDataBaseModelYks(std::string &userid, std::string &modelName, std::vector<CRtModelYkInfo> &yks) {
    return CSsqlMgr::getYks(userid, modelName, yks);
}

[[maybe_unused]] bool iotplat::CModelMgr::delModelYk(std::string &userid, std::string &modelName, std::string &ykName) {
    return (CRedisDbMgr::unLoadModelYk(userid, modelName, ykName) && CSsqlMgr::delYk(userid, modelName, ykName));
}

[[maybe_unused]] bool iotplat::CModelMgr::changeModelYk(const iotplat::CRtModelYkInfo &yk) {
    return (CSsqlMgr::changeYk(yk) && CRedisDbMgr::loadModelYk(yk.user, yk.model_name, yk.name));
}

bool CModelMgr::addModelParameter(CRtModelParameterInfo &parameter) {
    return (CSsqlMgr::addParameter(parameter) && CRedisDbMgr::loadModelParameter(parameter.user, parameter.model_name, parameter.name));
}

[[maybe_unused]] bool iotplat::CModelMgr::getRtModelParameter(std::string &userid, std::string &modelName, std::string &parameterName, iotplat::CRtModelParameterInfo &parameter) {
    return CRedisDbMgr::getRtModelParameter(userid, modelName, parameterName, parameter);
}

[[maybe_unused]] bool iotplat::CModelMgr::getRtModelParameters(std::string &userid, std::string &modelName, std::vector<CRtModelParameterInfo> &parameters) {
    std::unordered_set<std::string> names;
    if(!CRedisDbMgr::getModelParameterIndexs(userid, modelName, names))
        return false;

    for(std::string name : names) {
        CRtModelParameterInfo parameter;
        if(!CRedisDbMgr::getRtModelParameter(userid, modelName, name, parameter)) {
            return false;
        }
        parameters.push_back(parameter);
    }
    return true;
}

[[maybe_unused]] bool iotplat::CModelMgr::getDataBaseModelParameter(std::string &userid, std::string &modelName, std::string &parameterName, iotplat::CRtModelParameterInfo &parameter) {
    return CSsqlMgr::getParameter(userid, modelName, parameterName, parameter);
}

[[maybe_unused]] bool iotplat::CModelMgr::getDataBaseModelParameters(std::string &userid, std::string &modelName,std::vector<CRtModelParameterInfo> &parameters) {
    return CSsqlMgr::getParameters(userid, modelName, parameters);
}

[[maybe_unused]] bool iotplat::CModelMgr::delModelParameter(std::string &userid, std::string &modelName, std::string &parameterName) {
    return (CRedisDbMgr::unLoadModelParameter(userid, modelName, parameterName) && CSsqlMgr::delParameter(userid, modelName, parameterName));
}

[[maybe_unused]] bool iotplat::CModelMgr::changeModelParameter(const iotplat::CRtModelParameterInfo &parameter) {
    return (CSsqlMgr::changeParameter(parameter) && CRedisDbMgr::loadModelParameter(parameter.user, parameter.model_name, parameter.name));
}

bool CModelMgr::reloadModels() {
    std::ostringstream sql;
    sql << "SELECT " << userFieldName(USER_ENUM::EUserId) << " FROM " << t_user_name;
    GET_DB_HANDLE(CConfigs::EPlat);

    std::shared_ptr<CResultSet> res(db->query(sql.str().c_str()));
    if(!res)
        return false;

    while (res->next()) {
        std::string userid = res->asString(0);
        if(!CRedisDbMgr::loadUser(userid)) {
            return false;
        }

        std::ostringstream modelsql;
        modelsql << "SELECT " << mdoelFieldName(MODEL_ENUM::EName) << " FROM " << t_model_name;
        modelsql << " WHERE " << mdoelFieldName(MODEL_ENUM::EUser) << "='" << userid << "'";

        std::shared_ptr<CResultSet> modelres(db->query(modelsql.str().c_str()));
        if(!modelres) {
            THROW_ERROR_WITH_INFO(sql.str());
            return false;
        }

        while (modelres->next()) {
            std::string modelName  = modelres->asString(0);
            if(!CRedisDbMgr::loadModel(userid, modelName))
                return false;

            auto getSigs = [&db, userid, modelName](std::string table, std::vector<std::string>& sigs ) -> bool {
                std::ostringstream selsql;
                selsql << "SELECT " << baseSigFieldName(BASE_SIG_ENUM::EName) << " FROM " << table;
                selsql << " WHERE ";
                selsql << baseSigFieldName(BASE_SIG_ENUM::EUser) << "='" << userid << "'";
                selsql << " AND ";
                selsql << baseSigFieldName(BASE_SIG_ENUM::EModel_name) << "='" << modelName << "'";

                std::shared_ptr<CResultSet> sigres(db->query(selsql.str().c_str()));
                if(!sigres)
                    return false;

                while (sigres->next()) {
                    sigs.push_back(sigres->asString(0));
                }
                return true;
            };

            std::vector<std::string> sigs;
            if(!getSigs(t_yx_name, sigs))
                return false;

            for(auto& yx : sigs) {
                if(!CRedisDbMgr::loadModelYx(userid, modelName, yx))
                    return false;
            }

            sigs.clear();
            if(!getSigs(t_yc_name, sigs))
                return false;

            for(auto& yc : sigs) {
                if(!CRedisDbMgr::loadModelYc(userid, modelName, yc))
                    return false;
            }

            sigs.clear();
            if(!getSigs(t_yk_name, sigs))
                return false;

            for(auto& yk : sigs) {
                if(!CRedisDbMgr::loadModelYk(userid, modelName, yk))
                    return false;
            }

            sigs.clear();
            if(!getSigs(t_parameter_name, sigs))
                return false;

            for(auto& parameter : sigs) {
                if(!CRedisDbMgr::loadModelParameter(userid, modelName, parameter))
                    return false;
            }
        }
    }
    return true;
}

bool CModelMgr::reloadDevices() {
    std::ostringstream sql;
    sql << "SELECT " << userFieldName(USER_ENUM::EUserId) << " FROM " << t_user_name;
    GET_DB_HANDLE(CConfigs::EPlat);

    std::shared_ptr<CResultSet> res(db->query(sql.str().c_str()));
    if(!res)
        return false;

    while (res->next()) {
        std::string userid = res->asString(0);
        std::ostringstream seldevicesql;
        seldevicesql << "SELECT ";
        seldevicesql << deviceFieldName(DEVICE_ENUM::EName) << ",";
        seldevicesql << deviceFieldName(DEVICE_ENUM::EModelName);
        seldevicesql << " FROM " << t_device_name;
        seldevicesql << " WHERE " << deviceFieldName(DEVICE_ENUM::EUser) << "='" << userid << "'";
        std::shared_ptr<CResultSet> devres(db->query(seldevicesql.str().c_str()));
        if(!devres)
            return false;
        while (devres->next()) {
            std::string devName = devres->asString(0);
            std::string modelName = devres->asString(1);
            if(!CRedisDbMgr::loadDevice(userid, modelName, devName)) {
                return false;
            }
        }
    }
    return true;
}




















